package io;

import game.*;

import java.io.File;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

import org.jdom.*;

import util.Pair;

public class XMLInteractor {

	
	
	public static void main(String args[]){
		loadGames();
	}
	
	
	@SuppressWarnings("unchecked")
	public static Map<String, Player> loadPlayers() {
		Document document = new XMLReader().readXML(XMLInteractor.USERS_DOC_PATH);
		List<Element> elements = (List<Element>) document.getRootElement().getChildren();
		Map<String, Player> players = new HashMap<String, Player>();

		for (Element element : elements) {
			String name = element.getAttributeValue("login");
			String password = element.getChildText("password");
			String role = element.getChildText("role");
			if (role == null)
				role = "User";
				
			int ranking = Integer.parseInt(element.getChildText("ranking"));
			
			players.put(name, new Player(name, password, role, ranking));
		}		
		
		return players;
	}
	
	
	public static void savePlayers(Collection<Player> players) {
		Document document = new XMLReader().readXML(XMLInteractor.USERS_DOC_PATH);
		document.getRootElement().removeContent();
		
		for (Player user : players) {
			Element userElement = new Element("user");
			Attribute login = new Attribute("login", user.getLogin());	
			
			Element password = new Element("password");
			password.addContent(user.getPassword());
			
			Element role = new Element("role");
			role.addContent(user.getRole());
			
			Element ranking = new Element("ranking");
			ranking.addContent("" + user.getRanking());
			
			userElement.setAttribute(login);
			userElement.addContent(password);
			userElement.addContent(role);
			userElement.addContent(ranking);
			
			document.getRootElement().addContent(userElement);
		}		
		
		new XMLWriter().writeXml(document, XMLInteractor.USERS_DOC_PATH);
	}
	
	
	@SuppressWarnings("unchecked")
	public static Map<String, Game> loadGames() {
		Document document = new XMLReader().readXML(XMLInteractor.GAMES_DOC_PATH);
		List<Element> elements = (List<Element>) document.getRootElement().getChildren();
		Map<String, Game> games = new HashMap<String, Game>();

		for (Element element : elements){
			String klass = element.getAttributeValue("class");	
			Game instance;
			try {
				instance = (Game) Class.forName(klass).newInstance();
				games.put(instance.getName(), instance);
			} catch (Exception ex) {
				System.err.println("XMLInteractor::loadGames - Bad game class: " + klass);
			}
		}		
		
		return games;
	}
	
	
	public static void saveGames(Collection<Game> games) {
		Document document = new XMLReader().readXML(XMLInteractor.GAMES_DOC_PATH);
		document.getRootElement().removeContent();
		
		for (Game game : games) {
			Element element = new Element("game");
			Attribute attribute = new Attribute("class", game.getClass().getCanonicalName());	
			
			element.setAttribute(attribute);
			
			document.getRootElement().addContent(element);
		}		
		
		new XMLWriter().writeXml(document, XMLInteractor.GAMES_DOC_PATH);
	}

	
	public static MatchStatistics loadMatch(int matchId) {
		String fileName = findMatchFile(matchId);
		Document document = new XMLReader().readXML(fileName);
		MatchStatistics match = new MatchStatistics();
		Element matchElement = document.getRootElement();
		
		try {
			match.setMatchId(matchElement.getAttribute("id").getIntValue());
		} catch (DataConversionException e) {
			e.printStackTrace();
		}
		
		match.setGameName(matchElement.getAttributeValue("gameName"));
		
		match.setMoveCount(Integer.parseInt(matchElement.getChildText("moves")));
		match.setWinner(matchElement.getChildText("winner"));
		
		SimpleDateFormat formatter = new SimpleDateFormat("dd/MMM/yyyy kk:mm:ss");
		try {
			match.setDateStarted(formatter.parse(matchElement.getChildText("dateStarted")));
		} catch (ParseException e) {
		}
		
		try {
			match.setDateEnded(formatter.parse(matchElement.getChildText("dateEnded")));
		} catch (ParseException e) {
		}
		
		List<Pair<String,Integer>> rankingList = new ArrayList<Pair<String,Integer>>();
		List<Pair<String,Integer>> scoreList = new ArrayList<Pair<String,Integer>>();
		
		Element usersElement = matchElement.getChild("rankingAndScore").getChild("users");
		for (Element userElement : (List<Element>) usersElement.getChildren()) {
			String login = userElement.getAttributeValue("login");
			
			int score = 0;
			try {
				score = Integer.parseInt(userElement.getChildText("score"));
			} catch (Exception ex) {
			}
			
			int ranking = 0;
			try {
				ranking = Integer.parseInt(userElement.getChildText("ranking"));
			} catch (Exception ex) {
			}
			
			rankingList.add(new Pair<String, Integer>(login, ranking));
			scoreList.add(new Pair<String, Integer>(login, score));
		}
		
		match.setRankingPoints(rankingList);
		match.setScore(scoreList);

		return match;
	}

	
	
	public static void saveMatch(MatchStatistics match) {	
		Element matchStatsElement = new Element("match");
		Attribute matchIdAttribute = new Attribute("id", "" + match.getMatchId());
		Attribute gameNameAttribute = new Attribute("gameName", "" + match.getGameName());

		Element countMoves = new Element("moves");
		countMoves.setText("" + match.countMoves());
		
		Element winner = new Element("winner");
		winner.setText(match.getWinner());
		
		SimpleDateFormat formatter = new SimpleDateFormat("dd/MMM/yyyy kk:mm:ss");
		Element dateStarted = new Element("dateStarted");
		dateStarted.setText(formatter.format(match.getDateStarted()));
		
		Element dateEnded = new Element("dateEnded");
		dateEnded.setText(formatter.format(match.getDateEnded()));

		Element rankingScoreElement = new Element("rankingAndScore");
		Element usersElement = new Element("users");
		rankingScoreElement.addContent(usersElement);

		List<Pair<String,Integer>> rankingList = match.getRankingPoints();
		List<Pair<String,Integer>> scoreList = match.getScore();

		for(int i = 0; i < rankingList.size(); i++) {
			Pair scorePair = scoreList.get(i);
			Pair rankingPair = rankingList.get(i);

			Element userElement = new Element("user");
			Element rankingElement = new Element("ranking");
			Element scoreElement = new Element("score");
			Attribute login = new Attribute("login","" + scorePair.getFirst());

			rankingElement.setText("" + rankingPair.getSecond());
			scoreElement.setText("" + scorePair.getSecond());

			userElement.setAttribute(login);
			userElement.addContent(rankingElement);
			userElement.addContent(scoreElement);
			usersElement.addContent(userElement);			
		}

		matchStatsElement.setAttribute(matchIdAttribute);
		matchStatsElement.setAttribute(gameNameAttribute);
		matchStatsElement.addContent(countMoves);
		matchStatsElement.addContent(winner);
		matchStatsElement.addContent(dateStarted);
		matchStatsElement.addContent(dateEnded);
		matchStatsElement.addContent(rankingScoreElement);
		
		Document document = new Document();
		document.addContent(matchStatsElement);

		String fileName = match.getGameName() + " " + match.getPlayers() + " " + match.getMatchId();
		
		new XMLWriter().writeXml(document, fileName);
	}


	private static String findMatchFile(int matchId) {
		File dir = new File(System.getProperty("user.dir") + "/data/");
		for (String fileName : dir.list()) {
			if (fileName.contains(matchId + "")) 
				return fileName;
		}
		
		return null;
	}
	
	
	public static final String USERS_DOC_PATH = "users.xml";
	public static final String GAMES_DOC_PATH = "games.xml";
}

